/*
 * Copyright (c) 2018, Nordic Semiconductor
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package no.nordicsemi.android.nrfmesh;

import android.content.Intent;
import android.content.SharedPreferences;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import com.google.android.material.snackbar.Snackbar;

import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import dagger.hilt.android.AndroidEntryPoint;
import no.nordicsemi.android.mesh.transport.ProvisionedMeshNode;
import no.nordicsemi.android.nrfmesh.ble.ScannerActivity;
import no.nordicsemi.android.nrfmesh.databinding.FragmentNetworkBinding;
import no.nordicsemi.android.nrfmesh.dialog.DialogFragmentDeleteNode;
import no.nordicsemi.android.nrfmesh.dialog.DialogFragmentError;
import no.nordicsemi.android.nrfmesh.node.NodeConfigurationActivity;
import no.nordicsemi.android.nrfmesh.node.adapter.NodeAdapter;
import no.nordicsemi.android.nrfmesh.utils.Utils;
import no.nordicsemi.android.nrfmesh.viewmodels.SharedViewModel;
import no.nordicsemi.android.nrfmesh.widgets.ItemTouchHelperAdapter;
import no.nordicsemi.android.nrfmesh.widgets.RemovableItemTouchHelperCallback;
import no.nordicsemi.android.nrfmesh.widgets.RemovableViewHolder;
import no.nordicsemi.android.nrfmesh.autobind.MeshAutoConfigurator;

import static android.app.Activity.RESULT_OK;
//展示设备网络节点的列表，并允许用户进行配置、删除操作，管理和处理设备网络中的节点
@AndroidEntryPoint
public class NetworkFragment extends Fragment implements
        NodeAdapter.OnItemClickListener,
        ItemTouchHelperAdapter,
        DialogFragmentDeleteNode.DialogFragmentDeleteNodeListener {
    private FragmentNetworkBinding binding;
    private SharedViewModel mViewModel;

    private NodeAdapter mNodeAdapter;
    private MeshAutoConfigurator mMeshAutoConfigurator;

    private final ActivityResultLauncher<Intent> provisioner =
            registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), this::handleActivityResult);

    @Nullable
    @Override
    public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup viewGroup, @Nullable final Bundle savedInstanceState) {
        binding = FragmentNetworkBinding.inflate(getLayoutInflater());
        mViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);

        final ExtendedFloatingActionButton fab = binding.fabAddNode;
        final RecyclerView mRecyclerViewNodes = binding.recyclerViewProvisionedNodes;
        final View noNetworksConfiguredView = binding.noNetworksConfigured.getRoot();

        // Configure the recycler view
        mNodeAdapter = new NodeAdapter(this, mViewModel.getNodes());
        mNodeAdapter.setOnItemClickListener(this);

        // 初始化 Mesh 自动配置器
        mMeshAutoConfigurator = MeshAutoConfigurator.getInstance();
        mRecyclerViewNodes.setLayoutManager(new LinearLayoutManager(getContext()));
        mRecyclerViewNodes.addItemDecoration(new DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL));
        final ItemTouchHelper.Callback itemTouchHelperCallback = new RemovableItemTouchHelperCallback(this);
        final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemTouchHelperCallback);
        itemTouchHelper.attachToRecyclerView(mRecyclerViewNodes);
        mRecyclerViewNodes.setAdapter(mNodeAdapter);

        // Create view model containing utility methods for scanning
        mViewModel.getNodes().observe(getViewLifecycleOwner(), nodes -> {
            if (nodes != null && !nodes.isEmpty()) {
                noNetworksConfiguredView.setVisibility(View.GONE);
            } else {
                noNetworksConfiguredView.setVisibility(View.VISIBLE);
            }
            requireActivity().invalidateOptionsMenu();
        });

        mViewModel.isConnectedToProxy().observe(getViewLifecycleOwner(), isConnected -> {
            if (isConnected != null) {
                requireActivity().invalidateOptionsMenu();
            }
        });

        mRecyclerViewNodes.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull final RecyclerView recyclerView, final int dx, final int dy) {
                super.onScrolled(recyclerView, dx, dy);
                final LinearLayoutManager m = (LinearLayoutManager) recyclerView.getLayoutManager();
                if (m != null) {
                    if (m.findFirstCompletelyVisibleItemPosition() == 0) {
                        fab.extend();
                    } else {
                        fab.shrink();
                    }
                }
            }
        });

        fab.setOnClickListener(v -> {
            final Intent intent = new Intent(requireContext(), ScannerActivity.class);
            intent.putExtra(Utils.EXTRA_DATA_PROVISIONING_SERVICE, true);
            provisioner.launch(intent);
        });

        return binding.getRoot();
    }

    @Override
    public void onConfigureClicked(final ProvisionedMeshNode node) {
        // 检查是否取消选择
        boolean isCancel = false;   //默认为不取消选择false
        if (mNodeAdapter.getSelectedNode() != null && mNodeAdapter.getSelectedNode().getUnicastAddress() == node.getUnicastAddress()) {
            isCancel = true;
        }

        if (isCancel) {
            // 取消选择时，清除ViewModel中的选中状态
            mViewModel.clearSelectedMeshNode();
            // 通知适配器更新UI状态
            mNodeAdapter.setSelectedNode(null);
            mViewModel.displaySnackBar(requireActivity(), binding.container, "已取消选择节点", Snackbar.LENGTH_SHORT);
        } else {
            // 选中节点时，设置ViewModel中的选中状态
            mViewModel.setSelectedMeshNode(node);
            // 通知适配器更新UI状态
            mNodeAdapter.setSelectedNode(node);
            // 自动配置 AppKey（如果还没有配置的话）
            autoConfigureAppKey(node);

            final String message = "已选中节点: " + node.getNodeName() + " (地址: " +
                    String.format("0x%04X", node.getUnicastAddress()) + ")";
            mViewModel.displaySnackBar(requireActivity(), binding.container, message, Snackbar.LENGTH_LONG);

            // 跳转到节点配置界面
            final Intent meshConfigurationIntent = new Intent(requireActivity(), NodeConfigurationActivity.class);
            requireActivity().startActivity(meshConfigurationIntent);
        }
    }

    @Override
    public void onItemDismiss(final RemovableViewHolder viewHolder) {
        final int position = viewHolder.getAdapterPosition();
        if (!mNodeAdapter.isEmpty()) {
            final DialogFragmentDeleteNode fragmentDeleteNode = DialogFragmentDeleteNode.newInstance(position);
            fragmentDeleteNode.show(getChildFragmentManager(), null);
        }
    }

    @Override
    public void onItemDismissFailed(final RemovableViewHolder viewHolder) {
        //Do nothing
    }

    @Override
    public void onNodeDeleteConfirmed(final int position) {
        final ProvisionedMeshNode node = mNodeAdapter.getItem(position);
        if (mViewModel.getNetworkLiveData().getMeshNetwork().deleteNode(node)) {
            // 如果删除的是当前选中的节点，清除选中状态
            if (mNodeAdapter.getSelectedNode() != null &&
                    mNodeAdapter.getSelectedNode().getUnicastAddress() == node.getUnicastAddress()) {
                mNodeAdapter.setSelectedNode(null);
                mViewModel.clearSelectedMeshNode();
            }
            mViewModel.displaySnackBar(requireActivity(), binding.container, getString(R.string.node_deleted), Snackbar.LENGTH_LONG);
        }
    }

    @Override
    public void onNodeDeleteCancelled(final int position) {
        mNodeAdapter.notifyItemChanged(position);
    }

    /**
     * 自动配置 AppKey 的方法
     * 在用户选择节点后自动执行，无需用户手动配置
     */
    private void autoConfigureAppKey(final ProvisionedMeshNode node) {
        try {
            // 1. 初始化默认 AppKey（如果网络中还没有的话）
            mMeshAutoConfigurator.initDefaultAppKey(mViewModel.getMeshManagerApi());

            // 2. 自动绑定所有 Vendor Model
            mMeshAutoConfigurator.autoBindAllVendorModels(node, mViewModel.getMeshManagerApi());

            // 3. 显示配置成功的提示
            mViewModel.displaySnackBar(requireActivity(), binding.container,
                "AppKey 自动配置完成，现在可以进行波形操作", Snackbar.LENGTH_LONG);

            // 4. 设置 opCode 为 0xC0,并传递给CustomControlsActivity
            setOpCodeForVendorModels("0xC0");

            // 5. 确保节点被标记为已配置（防止MeshAutoConfigurator中的标记失效）
            if (!node.isConfigured()) {
                node.setConfigured(true);
                Log.d("NetworkFragment", "手动标记节点 " + node.getNodeName() + " 为已配置");
            }

        } catch (Exception e) {
            // 如果自动配置失败，显示错误信息但不影响节点选择
            mViewModel.displaySnackBar(requireActivity(), binding.container,
                "AppKey 自动配置失败: " + e.getMessage(), Snackbar.LENGTH_LONG);
        }
    }

    private void setOpCodeForVendorModels(String opCode){
        SharedPreferences prefs = requireContext().getSharedPreferences("AppPrefs", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = prefs.edit();
        editor.putString("opCode", opCode); // 保存为字符串
        editor.apply();
    }
    private void handleActivityResult(final ActivityResult result) {
        final Intent data = result.getData();
        if (result.getResultCode() == RESULT_OK && data != null) {
            final boolean provisioningSuccess = data.getBooleanExtra(Utils.PROVISIONING_COMPLETED, false);
            final DialogFragmentError fragmentConfigError;
            if (provisioningSuccess) {
                final boolean provisionerUnassigned = data.getBooleanExtra(Utils.PROVISIONER_UNASSIGNED, false);
                if (provisionerUnassigned) {
                    fragmentConfigError =
                            DialogFragmentError.newInstance(getString(R.string.title_init_config_error)
                                    , getString(R.string.provisioner_unassigned_msg));
                    fragmentConfigError.show(getChildFragmentManager(), null);
                } else {
                    final boolean compositionDataReceived = data.getBooleanExtra(Utils.COMPOSITION_DATA_COMPLETED, false);
                    final boolean defaultTtlGetCompleted = data.getBooleanExtra(Utils.DEFAULT_GET_COMPLETED, false);
                    final boolean appKeyAddCompleted = data.getBooleanExtra(Utils.APP_KEY_ADD_COMPLETED, false);
                    final boolean networkRetransmitSetCompleted = data.getBooleanExtra(Utils.NETWORK_TRANSMIT_SET_COMPLETED, false);
                    final String title = getString(R.string.title_init_config_error);
                    final String message;
                    if (compositionDataReceived) {
                        if (defaultTtlGetCompleted) {
                            if (appKeyAddCompleted) {
                                if (!networkRetransmitSetCompleted) {
                                    message = getString(R.string.init_config_error_app_key_msg);
                                    showErrorDialog(title, message);
                                }
                            } else {
                                message = getString(R.string.init_config_error_app_key_msg);
                                showErrorDialog(title, message);
                            }
                        } else {
                            message = getString(R.string.init_config_error_default_ttl_get_msg);
                            showErrorDialog(title, message);
                        }
                    } else {
                        message = getString(R.string.init_config_error_all);
                        showErrorDialog(title, message);
                    }
                }
            }
            requireActivity().invalidateOptionsMenu();
        }
    }

    private void showErrorDialog(@NonNull final String title, @NonNull final String message) {
        final DialogFragmentError dialogFragmentError = DialogFragmentError.newInstance(title, message);
        dialogFragmentError.show(getChildFragmentManager(), null);
    }
}
